package org.eraser.security.authentication;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.jetbrains.annotations.NotNull;
import org.springframework.http.HttpMethod;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

/**
 * AuthenticationFilter 也是一个认证过滤器 这个过滤器使用场景主要是在需要根据请求动态解析 AuthenticationManager 的情况下
 * 例如 假设一个系统有两组用户：员工和客户。这两组用户有特定的身份验证逻辑 并且有单独的数据存储。此外 这两组用户只能调用与他们相关的 URL
 * 请查看他的类说明
 * <p/>
 * AuthenticationFilter 是一个认证过滤器，它负责处理特定的身份验证请求。它的工作流程大致如下：
 * 当一个请求到达应用程序时，如果请求不匹配 setRequestMatcher(RequestMatcher)，那么这个过滤器不会做任何事情，而是继续执行过滤器链。
 * 如果匹配，那么…尝试将 HttpServletRequest 转换为 Authentication。如果结果为空，那么过滤器不会做任何事情，而是继续执行过滤器链。
 * 如果它确实创建了一个 Authentication…在 AuthenticationFilter(AuthenticationManager, AuthenticationConverter) 中指定的 AuthenticationManager 用于执行身份验证。
 * 在 AuthenticationFilter(AuthenticationManagerResolver, AuthenticationConverter) 中指定的 AuthenticationManagerResolver 用于从上下文中解析适当的身份验证管理器以执行身份验证。
 * 如果身份验证成功，那么将调用 AuthenticationSuccessHandler 并将身份验证设置在 SecurityContextHolder 上，否则将调用 AuthenticationFailureHandler（认证失败的处理器）。
 * <p/>
 * AuthenticationConverter 这个类用于从当前请求中解析出 Authentication 对象如: UsernamePasswordAuthenticationToken
 * attemptAuthentication 方法是真正执行认证的方法。 UsernamePasswordAuthenticationFilter 中也有这个方法
 * <p/>
 * 而 UsernamePasswordAuthenticationFilter 是专门用于处理基于用户名和密码的身份验证。当用户提交包含用户名和密码的表单时，UsernamePasswordAuthenticationFilter
 * 会拦截这个请求，从中提取出用户名和密码，并将它们封装成一个 UsernamePasswordAuthenticationToken。然后，这个令牌会被传递给 AuthenticationManager 进行身份验证。
 * <p/>
 * 根据以上描述 AuthenticationFilter 并不能满足我们的需求 我们来自定义实现 oauth2.0 的认证流程
 */
@Component
public class Oauth2CodeAuthenticationFilter extends OncePerRequestFilter {

    /**
     * 提供授权码的uri
     */
    private static final String oauth2_authorization_code_path = "/enoch/oidc/oauth2code";

    /**
     * private RequestMatcher requestMatcher = AnyRequestMatcher.INSTANCE; AnyRequestMatcher 所有匹配都返回 true
     */
    private final RequestMatcher requestMatcher = AntPathRequestMatcher.antMatcher(HttpMethod.GET, oauth2_authorization_code_path);

    public Oauth2CodeAuthenticationFilter() {
    }

    @Override
    protected void doFilterInternal(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull FilterChain filterChain) throws ServletException, IOException {
        /*
        拦截获取授权码的请求
         */
        if (!this.requestMatcher.matches(request)) {
            if (logger.isTraceEnabled()) {
                logger.trace("Did not match request to " + this.requestMatcher);
            }
            filterChain.doFilter(request, response);
        }

    }

}
